#include <cpp_primer.h>

using namespace std;

class Folder;

class Message {
    friend void swap(Message &lhs, Message &rhs);
    friend class Folder;

public:
    // folders被隐式初始化为空集合
    explicit Message(const string &str = "") : contents(str) {  }
    Message(const Message&);
    Message& operator=(const Message&);
    ~Message();

    // 从给定Folder集合中添加/删除Message
    void save(Folder &f);
    void remove(Folder &f);

private:
    string contents;        // 实际消息文本
    set<Folder*> folders;   // 包含本Message的Folder

    // 拷贝构造、拷贝赋值、析构函数需要的工具函数
    // 将Message添加到指定参数的Folder中
    void add_to_Folders(const Message &m);
    // 从folders中的每个Folder中删除Message
    void remove_from_Folders();
};


class Folder {
    friend class Message;

public:
    Folder() = default;
    Folder(const Folder&);
    Folder& operator=(const Folder&);
    ~Folder();

    void addMsg(Message*);
    void remMsg(Message*);

private:
    set<Message*> message;

    void add_to_Message(const Folder &f);
    void remove_from_Message();
};

void Message::save(Folder &f)
{
    folders.insert(&f); // 将给定Folder添加到我们的Folder列表中
    f.addMsg(this);     // 将本Message添加到f的Message集合中
}
void Message::remove(Folder &f)
{
    folders.erase(&f);
    f.remMsg(this);
}

void Message::add_to_Folders(const Message &m)
{
    for(auto f : m.folders)
        f->addMsg(this);    // 向该Folder添加一个指向本Message的指针
}

Message::Message(const Message &m)
    :contents(m.contents), folders(m.folders)
{
    add_to_Folders(m);
}

void Message::remove_from_Folders()
{
    for(auto f : folders)
        f->remMsg(this);
}

Message::~Message()
{
    remove_from_Folders();
}

Message& Message::operator=(const Message &rhs)
{
    remove_from_Folders();
    contents = rhs.contents;
    folders = rhs.folders;
    add_to_Folders(rhs);
    return *this;
}

void swap(Message &lhs, Message &rhs)
{
    using std::swap;
    for(auto f : lhs.folders)
        f->remMsg(&lhs);
    for(auto f : rhs.folders)
        f->remMsg(&rhs);

    swap(lhs.folders, rhs.folders);
    swap(lhs.contents, rhs.contents);

    for(auto f : lhs.folders)
        f->addMsg(&lhs);
    for(auto f : rhs.folders)
        f->addMsg(&rhs);
}



Folder::Folder(const Folder &f)
    :message(f.message)
{
    add_to_Message(f);
}

Folder& Folder::operator=(const Folder &f)
{
    remove_from_Message();
    message = f.message;
    add_to_Message(f);
    return *this;
}

Folder::~Folder()
{
    remove_from_Message();
}

void Folder::addMsg(Message* m)
{
    message.insert(m);
    m->folders.insert(this);
}

void Folder::remMsg(Message* m)
{
    message.erase(m);
    m->folders.erase(this);
}

void Folder::add_to_Message(const Folder &f)
{
    for(auto m : f.message)
    {
        m->folders.insert(this);
        message.insert(m);
    }
}

void Folder::remove_from_Message()
{
    for(auto m : message)
        m->folders.erase(this);
    message.clear();
}


int main()
{

    return 0;
}
